/*******************************************************************************
 * Copyright (c) 2001, 2002 Boris Pruessmann and others. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Common Public License v0.5 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors: Boris Pruessmann - Initial implementation. David Corbin - added
 * method to construct full path name
 ******************************************************************************/
package net.sourceforge.perforce.core.resources;

import java.io.File;
import java.io.InputStream;

import net.sourceforge.perforce.core.PerforceCorePlugin;
import net.sourceforge.perforce.core.PerforceException;
import net.sourceforge.perforce.core.api.IPerforceServer;
import net.sourceforge.perforce.core.api.IWhereResult;
import net.sourceforge.perforce.core.internal.Policy;
import net.sourceforge.perforce.core.syncinfo.FolderSyncInfo;
import net.sourceforge.perforce.core.syncinfo.ResourceSyncInfo;

import org.eclipse.core.resources.IStorage;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;

/**
 * @version $Revision: 488 $
 * @author <a href="mailto:bpruessmann@users.sourceforge.net">Boris
 *         Pruessmann</a>
 * @author <a href="mailto:dcorbin@users.sourceforge.net">David Corbin</a>
 */
public class RemoteFolder extends RemoteResource {
  // ---------------------------------------------------------------------------
  // Private Variables

  /** Stores the FolderSyncInfo. */
  private FolderSyncInfo folderSyncInfo;
  /** Stores the revision. */
  private String revision;

  // -------------------------------------------------------------------------
  // Public Constructors

  /**
   * Constructor for RemoteFolder.
   * 
   * @param server the perforce server.
   * @param parent the parent folder.
   * @param folderSyncInfo the sync info.
   * @param revision the revision
   */
  public RemoteFolder(IPerforceServer server, RemoteFolder parent, FolderSyncInfo folderSyncInfo,
      String revision) {
    Policy.assertNotNull(folderSyncInfo);

    setParent(parent);
    setServer(server);

    this.folderSyncInfo = folderSyncInfo;
    this.revision = revision;
  }

  //----------------------------------------------------------------------------
  // -- Public Methods

  @Override
  public String getDepotFilename() {
    return folderSyncInfo.getDepotFileName();
  }

  @Override
  public RemoteResource find(String name, IProgressMonitor monitor) throws PerforceException {
    if (name.equals(getDepotFilename())) {
      return this;
    }

    RemoteResource[] children = members(monitor);
    for (int i = 0, length = children.length; i < length; i++) {
      if (name.startsWith(children[i].getDepotFilename())) {
        return children[i].find(name, monitor);
      }
    }

    return null;
  }

  /**
   * Gets the name.
   * 
   * @return Returns a String
   */
  @Override
  public String getName() {
    // XXX TODO: getName in IRemoteResource should only return the name part.
    if (getParent() == null) {
      return folderSyncInfo.getDepotFileName();
    } else {
      return folderSyncInfo.getDepotFileName().substring(
          getParent().folderSyncInfo.getDepotFileName().length() + 1);
    }
  }

  /**
   * Returns the location.
   * 
   * @return the location.
   */
  public IPath getLocation() {
    try {
      IWhereResult whereResult = getServer().where(folderSyncInfo.getDepotFileName());
      if (whereResult == null) {
        return null;
      }

      String localPath = whereResult.getLocalFilename();
      return new Path(localPath.substring(0, localPath.length()));
    } catch (PerforceException e) {
      PerforceCorePlugin.log(e.getStatus());
      return null;
    }
  }

  /**
   * Returns the contained folders.
   * 
   * @param monitor the monitor
   * @return contained folders.
   */
  public RemoteFolder[] getFolders(IProgressMonitor monitor) {
    try {
      final FolderSyncInfo[] subFolders =
          getServer().dirs(folderSyncInfo.getDepotFileName() + "/*", monitor);

      final RemoteFolder[] result = new RemoteFolder[subFolders.length];
      for (int i = 0; i < subFolders.length; i++) {
        result[i] = new RemoteFolder(getServer(), this, subFolders[i], revision);
      }

      return result;
    } catch (PerforceException e) {
      PerforceCorePlugin.log(e.getStatus());
    }

    return new RemoteFolder[0];
  }

  /**
   * Returns the contained files.
   * 
   * @param monitor the monitor
   * @return the contained files.
   */
  public RemoteFile[] getFiles(IProgressMonitor monitor) {
    try {
      final ResourceSyncInfo[] files =
          getServer().fstat(folderSyncInfo.getDepotFileName() + "/*", monitor);

      final RemoteFile[] result = new RemoteFile[files.length];
      for (int i = 0; i < files.length; i++) {
        result[i] = new RemoteFile(getServer(), files[i], revision);
      }

      return result;
    } catch (PerforceException e) {
      PerforceCorePlugin.log(e.getStatus());
    }

    return new RemoteFile[0];
  }

  @Override
  public InputStream getContents(IProgressMonitor progress) {
    return null;
  }

  @Override
  public boolean isContainer() {
    return true;
  }

  @Override
  public ResourceSyncInfo getSyncInfo(IProgressMonitor monitor) {
    return null;
  }

  /**
   * Returns the revision.
   * 
   * @return the revision.
   */
  public String getRevision() {
    return revision;
  }

  @SuppressWarnings("unused")
  @Override
  public RemoteResource[] members(IProgressMonitor monitor) throws PerforceException {
    final RemoteResource[] folders = getFolders(monitor);
    final RemoteResource[] files = getFiles(monitor);
    final RemoteResource[] result = new RemoteResource[folders.length + files.length];
    System.arraycopy(folders, 0, result, 0, folders.length);
    System.arraycopy(files, 0, result, folders.length, files.length);

    return result;
  }

  /**
   * Returns the full name.
   * 
   * @return the full name.
   */
  public String getFullName() {
    if (getParent() != null) {
      return getParent().getFullName() + "/" + getName();
    }

    return getName();
  }

  /**
   * Sync the resource to the given revision. TODO: Wrong
   * 
   * @param revision the revision
   * @param monitor for progress feedback.
   * 
   * @throws PerforceException in case of an error.
   */
  public void sync(String revision, IProgressMonitor monitor) throws PerforceException {
    IPath location = getLocation();
    if (location != null) {
      String spec = location.toOSString() + File.separatorChar + "..."; //$NON-NLS-1$
      getServer().sync(spec, revision, monitor);
    } else {
      PerforceCorePlugin.getPlugin().info("Unable to find location and sync for " + getFullName());
    }
  }

  public String getComment() {
    return null;
  }

  public String getContentIdentifier() {
    return null;
  }

  public String getCreatorDisplayName() {
    return null;
  }

  public IStorage getBufferedStorage(IProgressMonitor monitor) {
    return null;
  }
}
